#include "ManejadorCandidato.h"
#include "../Entidades/Utils.h"

using namespace Manejadores;

ManejadorCandidato::ManejadorCandidato() {
	Configuracion* config = Configuracion::getInstancia();
	string pathDeDatos = config->getNombreArchivoCandidato();
	this->candidatos = new ArchivoDeEstructurasVariables(pathDeDatos);
	this->indicePorUnicidad = new HashExtensible("IndicePorUnicidadCandidato");
	this->indicePorLista = new ArbolBMas("IndiceCandidatoPorLista");
}

bool ManejadorCandidato::alta(Candidato* candidato) {

	string claveUnicidad = candidato->getLista()->getNombre();
	if (!indicePorUnicidad->existe(claveUnicidad)) {
		unsigned int posicionDelRegistro = candidatos->insertar(candidato);
		indicePorUnicidad->insertar(claveUnicidad, posicionDelRegistro);
		string claveFecha = Utils::convertirEnteroAString(candidato->getLista()->getEleccion()->getFecha());
		string claveCargo = candidato->getCargo()->getNombre();
		string claveLista = candidato->getLista()->getNombre();
		string clavePorLista = claveFecha + claveCargo + claveLista;
		indicePorLista->insertar(clavePorLista, posicionDelRegistro);

		indicePorUnicidad->exportarTxt("IndicePorUnicidadCandidato");
		indicePorLista->exportar("IndiceCandidatoPorLista");
		return true;
	} else
		return false;
}

bool ManejadorCandidato::baja(Candidato* candidato) {
	string claveUnicidad = candidato->getLista()->getNombre();
	IRegistroIndice* aBorrar = indicePorUnicidad->buscar(claveUnicidad);
	if (aBorrar->getOffsets()->size() > 0) {
		candidatos->borrar(candidato, aBorrar->getOffsets()->at(0));
		indicePorUnicidad->eliminar(claveUnicidad, aBorrar->getOffsets()->at(0));
		string claveFecha = Utils::convertirEnteroAString(candidato->getLista()->getEleccion()->getFecha());
		string claveCargo = candidato->getCargo()->getNombre();
		string claveNombre = candidato->getVotante()->getNombreYApellido();
		string clavePorLista = claveFecha + claveCargo + claveNombre;
		indicePorLista->suprimir(clavePorLista, aBorrar->getOffsets()->at(0));
		delete aBorrar;

		indicePorUnicidad->exportarTxt("IndicePorUnicidadCandidato");
		indicePorLista->exportar("IndiceCandidatoPorLista");
		return true;
	} else
		return false;

}

bool ManejadorCandidato::modificacion(Candidato* candidato) {

	string claveUnicidad = candidato->getLista()->getNombre();
	IRegistroIndice* viejaPosicion = indicePorUnicidad->buscar(claveUnicidad);
	unsigned int nuevaPosicion = candidatos->modificar(candidato, viejaPosicion->getOffsets()->at(0));
	if (viejaPosicion->getOffsets()->at(0) != nuevaPosicion) {
		indicePorUnicidad->modificar(claveUnicidad, viejaPosicion->getOffsets()->at(0), nuevaPosicion);
		string claveFecha = Utils::convertirEnteroAString(candidato->getLista()->getEleccion()->getFecha());
		string claveCargo = candidato->getCargo()->getNombre();
		string claveNombre = candidato->getVotante()->getNombreYApellido();
		string clavePorLista = claveFecha + claveCargo + claveNombre;
		indicePorLista->modificar(clavePorLista, viejaPosicion->getOffsets()->at(0), nuevaPosicion);
		return true;
	} else
		return false;
}

vector<Candidato*>* ManejadorCandidato::recuperarCandidatosPorLista(string fecha, string cargo, string nombreLista) {

	string clave = fecha + cargo + nombreLista;
	IRegistroIndice* registro = this->indicePorLista->buscar(clave);
	vector<Candidato*>* candidatos = new vector<Candidato*> ;
	if (registro != NULL && clave == registro->getClave()) {
		for (unsigned int i = 0; i < registro->getOffsets()->size(); i++) {
			Candidato* nuevoCandidato = new Candidato();
			this->candidatos->leer(nuevoCandidato, registro->getOffsets()->at(i));
			candidatos->push_back(nuevoCandidato);
		}
		delete registro;
	}
	return candidatos;

}

bool ManejadorCandidato::listarTodos(){
	bool toReturn = false;
	fstream txtFile;
	Configuracion* config = Configuracion::getInstancia();
	string path = config->getPathReportes() + "ListadoCandidatos.txt";
	txtFile.open(path.c_str(), ios::out);
	if (txtFile.bad()) {
		txtFile.open(path.c_str(), ios::out);
	}
	txtFile << "Cargo			Lista		Votante" << endl;
	txtFile << "================================================" << endl;

	vector<unsigned int>* offsets = this->indicePorUnicidad->getTodosLosDatos();
	if(!offsets->empty()){
		Candidato* candidato = new Candidato();
		cout << "Generando Archivo...." << endl;
		for (unsigned int i = 0; i < offsets->size(); ++i) {
			this->candidatos->leer(candidato, offsets->at(i));
			txtFile << candidato->getCargo()->getNombre() << "		"
					 << candidato->getLista()->getNombre() << "		"
					 << candidato->getVotante()->getDNI() << endl;
		}
		delete candidato;
		toReturn = true;
	}else{
		toReturn = false;
	}
	txtFile.close();
	system("clear");
	return toReturn;
}

ManejadorCandidato::~ManejadorCandidato() {
	delete this->candidatos;
	delete this->indicePorUnicidad;
	delete this->indicePorLista;
}
